<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./CDC_Pulse_Synchronizer_4phase.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Reliably passes a synchronous posedge pulse from one clock domain to another when we don't know anything about the relative clock frequencies or the pulse duration. *Uses a 4-phase asynchronous handshake.*">
<title>CDC Pulse Synchronizer 4phase</title>
</head>
<body>

<p class="inline bordered"><b><a href="./CDC_Pulse_Synchronizer_4phase.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Clock Domain Crossing (CDC) Pulse Synchronizer (4-phase handshake)</h1>
<p>Reliably passes a synchronous posedge pulse from one clock domain to
 another when we don't know anything about the relative clock frequencies or
 the pulse duration. <em>Uses a 4-phase asynchronous handshake.</em></p>
<p>The recommended input is a single-cycle pulse in the sending clock domain.
 The output is a single-cycle pulse in the receiving clock domain.</p>
<div class="bordered">

 Unless you *really* need to save a few gates, I would recommend you instead
 use the [2-phase handshake Pulse
 Synchronizer](./CDC_Pulse_Synchronizer_2phase.html), as it can accept input
 pulses at twice the maximum rate. This 4-phase implementation exists for
 comparison and education.

 </div>

<h2>Theory of Operation</h2>
<p>We can't simply use a <a href="./CDC_Bit_Synchronizer.html">CDC Synchronizer</a> to
 pass a pulse of unknown duration between clock domains of unknown relation,
 as the receiving clock may not be able to sample the pulse correctly. So,
 we solve this by:</p>
<ul>
<li>first latching the incoming pulse into a level signal,</li>
<li>synchronizing that level signal into the receiving clock domain,</li>
<li>using that synchronized level signal to generate a pulse, </li>
<li>synchronizing that same level back into the sending clock domain,</li>
<li>using that synchronized level to clear the original level signal.</li>
</ul>
<p>This process then happens all over again with the cleared level signal,
 which does not generate a pulse in the receiving clock domain, until the
 system is back into its original rest state, ready to receive another input
 pulse. This process of raising a signal, waiting for a response to rise,
 then dropping the first signal, then waiting for the response to drop, is
 a 4-phase asynchronous handshake. It does not depends on the timing of the
 signals, only their sequence.</p>
<h2>Input Pulse Frequency Limit</h2>
<p>The time taken for the 4-phase handshake to complete puts an upper limit on
 the input pulse rate, that also depends on the receiving clock frequency.
 If we exceed this rate, input pulses will be lost, as the input pulse latch
 will have not been cleared yet.</p>
<p>At the upper limit, when the receiving clock frequency is fast enough to be
 "infinite" from the point of view of the sending clock (i.e.: the handshake
 response arrives soon enough within a single cycle of the sending clock to
 meet setup timing), then we only need to sum up the latencies on the sending
 clock side:</p>
<ol>
<li>Latching (or clearing) the input pulse: 1 cycle</li>
<li>CDC into the receving clock domain: 0 cycles</li>
<li>CDC back into the sending clock domain: 3 cycles (worst case)</li>
<li>The input latch now clears, and the steps 1, 2, and 3 repeat.</li>
</ol>
<p>Thus there must be <em>at an absolute minimum</em> 8 idle sending clock cycles
 between input pulses, or one input pulse every 9th sending clock cycle.
 (We can't overlap the clearing and latching, since clear has priority over
 input data in a <a href="./Register.html">Register</a>.) Fortunately, we don't have to
 compute inter-pulse delays for every possible sending to receiving clock
 frequency ratio a system will encounter. We can instead signal <code>ready</code> on
 the sending side by noting when both the initial sending level and the
 returned response are low, denoting a system at rest ready for the next
 4-phase handshake.</p>

<pre>
`default_nettype none

module <a href="./CDC_Pulse_Synchronizer_4phase.html">CDC_Pulse_Synchronizer_4phase</a>
#(
    parameter CDC_EXTRA_DEPTH   = 0  // 0 or greater, if necessary
)
(
    input   wire    sending_clock,
    input   wire    sending_pulse_in,
    output  reg     sending_ready,

    input   wire    receiving_clock,
    output  wire    receiving_pulse_out
);

    initial begin
        sending_ready = 1'b0;
    end
</pre>

<p>Capture the sending pulse into a level, and clear the latch once the level
 has passed into and returned from the receiving clock domain <em>and the
 sending pulse has ended</em>. This gating prevents a cycle of latch set/reset
 if the sending pulse is longer than the round-trip latency of level signal
 to and back from the receiving clock domain, causing a train of pulses in
 the receiving clock domain. </p>

<pre>
    wire sending_level;
    reg  clear_sending = 1'b0;
    wire level_response;

    always @(*) begin
        clear_sending = (level_response == 1'b1) && (sending_pulse_in == 1'b0);
    end

    <a href="./Pulse_Latch.html">Pulse_Latch</a>
    #(
        .RESET_VALUE (1'b0)
    )
    sending_pulse_capture
    (
        .clock          (sending_clock),
        .clear          (clear_sending),
        .pulse_in       (sending_pulse_in),
        .level_out      (sending_level)
    );
</pre>

<p>Pass the latched sending pulse to the receiving clock domain</p>

<pre>
    wire receiving_level;

    <a href="./CDC_Bit_Synchronizer.html">CDC_Bit_Synchronizer</a>
    #(
        .EXTRA_DEPTH        (CDC_EXTRA_DEPTH)
    )
    to_receiving
    (
        .receiving_clock    (receiving_clock),
        .bit_in             (sending_level),
        .bit_out            (receiving_level)
    );
</pre>

<p>Now pass the synchronized level back to the sending clock domain to
 signal that the CDC is complete and to clear the latch.</p>

<pre>
    <a href="./CDC_Bit_Synchronizer.html">CDC_Bit_Synchronizer</a>
    #(
        .EXTRA_DEPTH        (CDC_EXTRA_DEPTH)
    )
    to_sending
    (
        .receiving_clock    (sending_clock),
        .bit_in             (receiving_level),
        .bit_out            (level_response)
    );
</pre>

<p>In parallel to all of the above, signal when both the sending level and the
 returned level from the receiving clock domain are low, indicating
 readiness for the next 4-phase handshake. <em>An input pulse sent while ready
 is low will be lost.</em></p>

<pre>
    always @(*) begin
        sending_ready = (sending_level == 1'b0) && (level_response == 1'b0);
    end
</pre>

<p>Finally, convert the receiving level to a pulse in the receiving clock domain</p>

<pre>
    <a href="./Pulse_Generator.html">Pulse_Generator</a>
    receiving_level_to_pulse
    (
        .clock              (receiving_clock),
        .level_in           (receiving_level),
        .pulse_posedge_out  (receiving_pulse_out),
        // verilator lint_off PINCONNECTEMPTY
        .pulse_negedge_out  (),
        .pulse_anyedge_out  ()
        // verilator lint_on  PINCONNECTEMPTY
    );

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

